home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / exec / deallocate.c < prev    next >
C/C++ Source or Header  |  1996-09-13  |  5KB  |  189 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: deallocate.c,v 1.5 1996/09/13 17:51:23 digulla Exp $
  4.     $Log: deallocate.c,v $
  5.     Revision 1.5  1996/09/13 17:51:23  digulla
  6.     Use IPTR
  7.  
  8.     Revision 1.4  1996/08/13 13:56:00  digulla
  9.     Replaced __AROS_LA by __AROS_LHA
  10.     Replaced some __AROS_LH*I by __AROS_LH*
  11.     Sorted and added includes
  12.  
  13.     Revision 1.3  1996/08/01 17:41:09  digulla
  14.     Added standard header for all files
  15.  
  16.     Desc:
  17.     Lang:
  18. */
  19. #include <exec/execbase.h>
  20. #include <exec/alerts.h>
  21. #include <aros/libcall.h>
  22. #include "machine.h"
  23. #include "memory.h"
  24.  
  25. /*****************************************************************************
  26.  
  27.     NAME */
  28.     #include <exec/memory.h>
  29.     #include <clib/exec_protos.h>
  30.  
  31.     __AROS_LH3(void, Deallocate,
  32.  
  33. /*  SYNOPSIS */
  34.     __AROS_LHA(struct MemHeader *, freeList,    A0),
  35.     __AROS_LHA(APTR,               memoryBlock, A1),
  36.     __AROS_LHA(ULONG,              byteSize,    D0),
  37.  
  38. /*  LOCATION */
  39.     struct ExecBase *, SysBase, 32, Exec)
  40.  
  41. /*  FUNCTION
  42.     Free block of memory associated with a given MemHandler structure.
  43.  
  44.     INPUTS
  45.     freeList    - Pointer to the MemHeader structure
  46.     memoryBlock - Pointer to the memory to be freed
  47.     byteSize    - Size of the block
  48.  
  49.     RESULT
  50.  
  51.     NOTES
  52.     The start and end borders of the block are aligned to
  53.     a multiple of sizeof(struct MemChunk) and to include the block.
  54.  
  55.     EXAMPLE
  56.  
  57.     BUGS
  58.  
  59.     SEE ALSO
  60.     Allocate()
  61.  
  62.     INTERNALS
  63.  
  64.     HISTORY
  65.     18-09-95    created by m. fleischer
  66.     15-10-95    more consistency checks added
  67.  
  68. ******************************************************************************/
  69. {
  70.     __AROS_FUNC_INIT
  71.  
  72.     struct MemChunk *p1, *p2, *p3;
  73.     UBYTE *p4;
  74.  
  75.     /* If there is no memory free nothing */
  76.     if(!byteSize)
  77.     return;
  78.  
  79.     /* Align size to the requirements */
  80.     byteSize+=(IPTR)memoryBlock&(MEMCHUNK_TOTAL-1);
  81.     byteSize=(byteSize+MEMCHUNK_TOTAL-1)&~(MEMCHUNK_TOTAL-1);
  82.  
  83.     /* Align the block as well */
  84.     memoryBlock=(APTR)((IPTR)memoryBlock&~(MEMCHUNK_TOTAL-1));
  85.  
  86.     /*
  87.     The free memory list is only single linked, i.e. to insert
  88.     elements into the list I need the node as well as it's
  89.     predessor. For the first element I can use freeList->mh_First
  90.     instead of a real predessor.
  91.     */
  92.     p1=(struct MemChunk *)&freeList->mh_First;
  93.     p2=freeList->mh_First;
  94.  
  95.     /* Start and end(+1) of the block */
  96.     p3=(struct MemChunk *)memoryBlock;
  97.     p4=(UBYTE *)p3+byteSize;
  98.  
  99.     /* No chunk in list? Just insert the current one and return. */
  100.     if(p2==NULL)
  101.     {
  102.     p3->mc_Bytes=byteSize;
  103.     p3->mc_Next=NULL;
  104.     p1->mc_Next=p3;
  105.     freeList->mh_Free+=byteSize;
  106.     return;
  107.     }
  108.  
  109.     /* Follow the list to find a place where to insert our memory. */
  110.     do
  111.     {
  112. #if !defined(NO_CONSISTENCY_CHECKS)
  113.     /*
  114.         Do some constistency checks:
  115.         1. All MemChunks must be aligned to MEMCHUNK_TOTAL.
  116.         2. The end (+1) of the current MemChunk
  117.            must be lower than the start of the next one.
  118.     */
  119.     if(  ((IPTR)p2|p2->mc_Bytes)&(MEMCHUNK_TOTAL-1)
  120.         ||(  (UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p2->mc_Next
  121.         &&p2->mc_Next!=NULL))
  122.         Alert(AN_MemCorrupt|AT_DeadEnd);
  123. #endif
  124.     /* Found a block with a higher address? */
  125.     if(p2>=p3)
  126.     {
  127. #if !defined(NO_CONSISTENCY_CHECKS)
  128.         /*
  129.         If the memory to be freed overlaps with the current
  130.         block something must be wrong.
  131.         */
  132.         if(p4>(UBYTE *)p2)
  133.         {
  134.         Alert(AN_FreeTwice);
  135.         return;
  136.         }
  137. #endif
  138.         /* End the loop with p2 non-zero */
  139.         break;
  140.     }
  141.     /* goto next block */
  142.     p1=p2;
  143.     p2=p2->mc_Next;
  144.  
  145.     /* If the loop ends with p2 zero add it at the end. */
  146.     }while(p2!=NULL);
  147.  
  148.     /* If there was a previous block merge with it. */
  149.     if(p1!=(struct MemChunk *)&freeList->mh_First)
  150.     {
  151. #if !defined(NO_CONSISTENCY_CHECKS)
  152.     /* Check if they overlap. */
  153.     if((UBYTE *)p1+p1->mc_Bytes>(UBYTE *)p3)
  154.     {
  155.         Alert(AN_FreeTwice);
  156.         return;
  157.     }
  158. #endif
  159.     /* Merge if possible */
  160.     if((UBYTE *)p1+p1->mc_Bytes==(UBYTE *)p3)
  161.         p3=p1;
  162.     else
  163.         /* Not possible to merge */
  164.         p1->mc_Next=p3;
  165.     }else
  166.     /*
  167.         There was no previous block. Just insert the memory at
  168.         the start of the list.
  169.     */
  170.     p1->mc_Next=p3;
  171.  
  172.     /* Try to merge with next block (if there is one ;-) ). */
  173.     if(p4==(UBYTE *)p2&&p2!=NULL)
  174.     {
  175.     /*
  176.        Overlap checking already done. Doing it here after
  177.        the list potentially changed would be a bad idea.
  178.     */
  179.     p4+=p2->mc_Bytes;
  180.     p2=p2->mc_Next;
  181.     }
  182.     /* relink the list and return. */
  183.     p3->mc_Next=p2;
  184.     p3->mc_Bytes=p4-(UBYTE *)p3;
  185.     freeList->mh_Free+=byteSize;
  186.     return;
  187.     __AROS_FUNC_EXIT
  188. } /* Deallocate */
  189.